import 'package:built_collection/built_collection.dart';
import 'package:backend.core/core/domain/entities/web/yookassa/yookassa_pending_order.dart';
import 'package:equatable/equatable.dart';
import 'package:mongo_dart/mongo_dart.dart';
import 'package:backend.purchases/domain/repositories/yookassa_pending_order_repository/repository.dart';

part 'dtos/pending_order_dto.dart';

const _kPendingOrderCollectionKey = 'yookassa_pending_orders';

class YookassaPendingOrderRepositoryImpl implements YookassaPendingOrderRepository {
  const YookassaPendingOrderRepositoryImpl({
    required Db db,
  }) : _db = db;

  final Db _db;

  @override
  Future<YookassaPendingOrder?> findPendingOrderByYookassaPaymentId({
    required String yookassaPaymentId,
  }) async {
    final collection = _db.collection(_kPendingOrderCollectionKey);

    final pendingOrderJson = await collection.findOne(
      where.eq(_kPendingOrderYookassaApiPendingPaymentIdKey, yookassaPaymentId),
    );

    if (pendingOrderJson == null) {
      return null;
    }

    final pendingOrderDto = _PendingOrderDto.fromJson(pendingOrderJson);
    final pendingOrder = pendingOrderDto.toEntity();

    return pendingOrder;
  }

  @override
  Future<BuiltList<YookassaPendingOrder>> findUserPendingOrders({
    required String userId,
  }) async {
    final collection = _db.collection(_kPendingOrderCollectionKey);

    final pendingOrderStream = collection.find(
      where.eq(_kPendingOrderUserIdKey, userId),
    );

    final pendingOrderJsons = await pendingOrderStream.toList();

    final pendingOrders = pendingOrderJsons.map((pendingOrderJson) {
      return _PendingOrderDto.fromJson(pendingOrderJson).toEntity();
    }).toBuiltList();

    return pendingOrders;
  }

  @override
  Future<BuiltList<YookassaPendingOrder>> findAllPendingOrders() async {
    final collection = _db.collection(_kPendingOrderCollectionKey);

    final pendingOrderStream = collection.find();

    final pendingOrderJsons = await pendingOrderStream.toList();

    final pendingOrders = pendingOrderJsons.map((pendingOrderJson) {
      return _PendingOrderDto.fromJson(pendingOrderJson).toEntity();
    }).toBuiltList();

    return pendingOrders;
  }

  @override
  Future<void> deletePendingOrderByYookassaPaymentId({
    required String yookassaPaymentId,
  }) async {
    final collection = _db.collection(_kPendingOrderCollectionKey);

    await collection.deleteOne(
      where.eq(_kPendingOrderYookassaApiPendingPaymentIdKey, yookassaPaymentId),
    );
  }

  @override
  Future<void> upsertPendingOrder({
    required YookassaPendingOrder pendingOrder,
  }) async {
    final collection = _db.collection(_kPendingOrderCollectionKey);

    final pendingOrderDto = _PendingOrderDto.fromEntity(pendingOrder);
    final pendingOrderJson = pendingOrderDto.toJson();

    await collection.replaceOne(
      where.eq(_kPendingOrderIdKey, pendingOrder.id),
      pendingOrderJson,
      upsert: true,
    );
  }
}
